/**
 * Created by henian.xu on 2019/10/22.
 *
 */

import Axios from 'axios';
import { hasOwn } from 'utils/index';
import Qs from 'qs';
import mergeConfig, { defaultExtendConfig } from './defaultConfig';
import {
  requestSuccess,
  requestFail,
  responseSuccess,
  responseFail,
  getExtendConfig,
} from './interceptors';

// 全局唯一的 axios 实例
const axios = Axios.create(mergeConfig);

// 设置全局拦截器
axios.interceptors.request.use(requestSuccess, requestFail);
axios.interceptors.response.use(responseSuccess, responseFail);

// 创建取消令牌
export function createCancelToken() {
  return Axios.CancelToken.source();
}

// 设置内部扩展配置
function setInsideConfig(config) {
  const cancelSource = config.cancelSource || createCancelToken();
  const extendConfig = {
    cancelSource,
    ...defaultExtendConfig,
  };

  Object.keys(defaultExtendConfig).forEach((key) => {
    if (hasOwn(config, key)) {
      extendConfig[key] = config[key];
    }
  });

  if (hasOwn(config, 'isMock')) {
    extendConfig.isMock = config.isMock;
  }

  cancelSource.token.extendConfig = extendConfig;
  return {
    ...config,
    cancelToken: cancelSource.token,
  };
}

function requestReturn(result) {
  const { config } = result;
  const extendConfig = getExtendConfig(config);
  return extendConfig && extendConfig.isAxiosResponseData
    ? result.data
    : result;
}

/**
 * get 请求
 * @param url
 * @param params 对应 axios 中的 params
 * @param config
 */
export function get(url, params = {}, config = {}) {
  const cfg = {
    ...setInsideConfig({
      ...config,
      methodsPath: (this && this.url) || url,
    }),
    params: {
      ...mergeConfig.params,
      _T: new Date().getTime(),
      ...params,
    },
  };
  return axios.get(url, cfg).then((result) => requestReturn(result));
}

/**
 * post 请求
 * @param url
 * @param params 对应 axios 中的 data, 如果有 url 上的参数应该写在 config.params 中
 * @param config
 */
export function post(url, params, config = {}) {
  const cfg = setInsideConfig({
    isCancelBefore: false, // 默认值与get的相反,取消之后的请求
    ...config,
    params: {
      ...mergeConfig.params,
      ...config.params,
    },
    methodsPath: (this && this.url) || url,
  });
  return axios
    .post(
      url,
      {
        ...mergeConfig.data,
        ...params,
      },
      cfg,
    )
    .then((result) => requestReturn(result));
}

/**
 * postJson 请求
 * @param url
 * @param params
 * @param config
 */
export function postJson(url, params, config = {}) {
  return post(url, params, {
    ...config,
    headers: { 'Content-Type': 'application/json' },
    // paramsSerializer: () => '',
    transformRequest: [(data) => JSON.stringify(data)],
  });
}

/**
 * 页面跳转
 */
export function href(url, params = {}, { newWindow = false } = {}) {
  if (newWindow) {
    window.open(`${mergeConfig.baseURL + url}?${Qs.stringify(params)}`);
  } else {
    window.location.href = `${mergeConfig.baseURL + url}?${Qs.stringify(
      params,
    )}`;
  }
}
